/*+********************************************************
Filename: simpleHAL.c
Description: simple implementation of hardware access for 
             ALIENTEK stm32f407 Explorer board
Modification:
  2023.04.02 H.Zheng creation
*********************************************************-*/
#include "my_stm32f4xx.h"
#include "simpleHAL.h"
#include <stdio.h>

/**
 *  init system clock to 168MHz
 */
void shalInitSysClock(void){
	RCC->CR|=0x00000001;
	RCC->CFGR=0x00000000;
	RCC->CR&=0xFEF6FFFF;
	RCC->PLLCFGR=0x24003010;
	RCC->CR&=~(1<<18);
	RCC->CIR=0x00000000;
	RCC->CR|=1<<16;
	while((RCC->CR&(1<<17))==0) { //wait for HSE ready
	}
	RCC->APB1ENR|=1<<28;
	PWR->CR|=3<<14;
	RCC->CFGR|=(0<<4)|(5<<10)|(4<<13);
	RCC->CR&=~(1<<24);
	RCC->PLLCFGR=8|(336<<6)|(((2>>1)-1)<<16)|(7<<24)|(1<<22);
	RCC->CR|=1<<24;
	while((RCC->CR&(1<<25))==0){//wait for pll ready
	}
	FLASH->ACR|=1<<8;
	FLASH->ACR|=1<<9;
	FLASH->ACR|=1<<10;
	FLASH->ACR|=5<<0;
	RCC->CFGR&=~(3<<0);
	RCC->CFGR|=2<<0;
	while((RCC->CFGR&(3<<2))!=(2<<2)){//wait for main clock ready
	}
}

/**
 *  init LED on GF9 and GF10
 */
#define GF9_VALUE *((volatile unsigned int *)0x424282A4)
#define GF10_VALUE *((volatile unsigned int *)0x424282A8)
	
void shalInitLed(void){
	RCC->AHB1ENR |= 0x1<<5;  //enable clock
	GPIOF->MODER |= 0x5<<18; //GF9&GF10 mode output
	GF9_VALUE = 1;
	GF10_VALUE = 1;
}

/**
 *  simple output ctrl for GF9 and GF10
 */
void shalSetLed(unsigned int vLedNum, unsigned int vLedState){
	if (vLedNum == LED0) {
		if (vLedState == LED_ON) {
			GF9_VALUE = 0;
		}else if (vLedState == LED_TOGGLE) {
			GF9_VALUE = !GF9_VALUE;
		}else {
			GF9_VALUE = 1;
		}
	}else {
		if (vLedState == LED_ON) {
			GF10_VALUE = 0;
		}else if (vLedState == LED_TOGGLE) {
			GF10_VALUE = !GF10_VALUE;
		}else {
			GF10_VALUE = 1;
		}
	}
}

/**
 *  enable UART1 tx on PA9&PA10
 */
void shalInitUart1(void){
	RCC->AHB1ENR|=1<<0;
	RCC->APB2ENR|=1<<4;
	GPIOA->MODER &= ~(0x0f<<18); 
	GPIOA->MODER |= 0x0a<<18; //set PA9&PA10 as alternate function
  GPIOA->AFR[1]&=~(0x0FF<<4);
	GPIOA->AFR[1]|=(uint32_t)0x77<<4;

 	USART1->BRR=0x02d9;
	USART1->CR1&=~(1<<15); 
	USART1->CR1|=1<<3;  	//enable tx only
	USART1->CR1|=1<<13;   //enable uart
}

/**
 * redefine fputc to allow the use of printf
 * following codes are copied from www.openedv.com's demo code uart.c
 */

#pragma import(__use_no_semihosting)             
struct __FILE 
{ 
	int handle; 
}; 
FILE __stdout;       
void _sys_exit(int x) 
{ 
	x = x; 
} 

int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);
	USART1->DR = (uint8_t) ch;      
	return ch;
}

